<template>
  <q-modal v-model="opened" :content-css="{minWidth: '80vw', minHeight: '80vh'}" @hide="close" @show="openSvg">
    <q-modal-layout ref="svgModal">
      <q-toolbar slot="header">
        <q-btn flat round dense @click="opened = false" icon="reply"/>
        <q-toolbar-title>Projects&Services&Hosts</q-toolbar-title>
      </q-toolbar>
        <q-tabs animated swipeable inverted color="secondary" align="justify">
          <q-tab default name="svg" slot="title" icon="insert_photo"/>
          <q-tab name="table" slot="title" icon="grid_on" />
          <q-tab-pane name="svg" keep-alive>
            <svg :width="width" :height="height" ref="prjSvg"></svg>
          </q-tab-pane>
          <q-tab-pane name="table">
            <div class="row">
              <div class="col-xs-12 col-sm-12 col-md-3">
                <q-card class="q-ma-sm">
                  <q-card-title class="card_head">主要信息</q-card-title>
                  <q-card-main>
                    <tr class="svgTable"><th>主机名</th><th>IP地址</th><th>状态</th></tr>
                    <tr class="svgTable" v-for="(value) in this.svgTable.projectHosts" :key="value.id">
                      <td>{{value.hostname}}</td>
                      <td>{{value.ip}}</td>
                      <td>{{value.status}}</td>
                    </tr>
                  </q-card-main>
                </q-card>
              </div>
              <div class="col-xs-12 col-sm-12 col-md-3">
                <q-card class="q-ma-sm">
                  <q-card-title class="card_head">服务主机对应表</q-card-title>
                  <q-card-main>
                    <tr class="svgTable"><th>主机名</th><th>IP地址</th></tr>
                    <tr class="svgTable" v-for="(value) in this.svgTable.serviceHosts" :key="value.id">
                      <td>{{value.hostname}}</td>
                      <td>{{value.ip}}</td>
                    </tr>
                  </q-card-main>
                </q-card>
              </div>
              <div class="col-xs-12 col-sm-12 col-md-6">
                <q-card class="q-ma-sm">
                  <q-card-title class="card_head">服务表</q-card-title>
                  <q-card-main>
                    <tr class="svgTable"><th>服务名</th><th>内网IP</th><th>内网域名</th><th>外网IP</th><th>外网域名</th></tr>
                    <tr class="svgTable" v-for="(value) in this.svgTable.services" :key="value.id">
                      <td>{{value.name}}</td>
                      <td>{{value.innerIp}}</td>
                      <td>{{value.innerUrl}}</td>
                      <td>{{value.OutterIpSource__ipAddress}}</td>
                      <td>{{value.url}}</td>
                    </tr>
                  </q-card-main>
                </q-card>
              </div>
            </div>
          </q-tab-pane>
        </q-tabs>
    </q-modal-layout>
  </q-modal>
</template>

<script>
import * as d3 from 'd3'
import {ellipseForce} from 'plugins/ellipseForce'
import { fetch } from 'plugins/axios'
export default {
  name: 'ProjectSvg',
  data () {
    return {
      opened: false,
      graph: {},
      svgTable: {},
      simulation: '',
      link: '',
      node: '',
      text: '',
      width: null,
      height: null
    }
  },
  props: {
    svgDialog: {
      type: Boolean,
      default: false
    },
    projectId: {
      type: Number,
      default: null
    }
  },
  methods: {
    close () {
      this.$emit('upSvg')
      this.$refs.prjSvg.innerHTML = ''
      this.svgTable = {}
    },
    openSvg () {
      fetch('/project/get_svg/', {
        opt: this.projectId
      }).then((response) => {
        this.graph = JSON.parse(response)
        this.shwoGraph()
      }).catch((error) => {
        alert(error.response)
      })
      fetch('/project/get_svgTable/', {
        opt: this.projectId
      }).then((response) => {
        this.svgTable = JSON.parse(response)
      }).catch((error) => {
        alert(error.response)
      })
    },
    shwoGraph () {
      this.width = this.$refs.svgModal.$el.clientWidth - 20
      this.height = this.$refs.svgModal.$el.clientHeight - 125
      let graphs = this.graph
      let svg = d3.select('svg')
      let width = this.width
      let height = this.height
      let color = d3.scaleOrdinal(d3.schemeCategory20)
      let nd
      for (var i = 0; i < graphs.nodes.length; i++) {
        nd = graphs.nodes[i]
        nd.rx = nd.name.length * 5.5
        nd.ry = 12
      }
      this.simulation = d3.forceSimulation()
        .force('link', d3.forceLink().id(function (d) {
          return d.id
        }))
        .force('collide', ellipseForce(6, 0.5, 5))
        .force('center', d3.forceCenter(width / 2, height / 2))
      this.link = svg.append('g')
        .attr('class', 'link')
        .selectAll('line')
        .data(graphs.links)
        .enter().append('line')
        .attr('stroke-width', function (d) {
          return Math.sqrt(d.value)
        })
      this.node = svg.append('g')
        .attr('class', 'node')
        .selectAll('ellipse')
        .data(graphs.nodes)
        .enter().append('ellipse')
        .attr('rx', function (d) {
          return d.rx
        })
        .attr('ry', function (d) {
          return d.ry
        })
        .attr('fill', function (d) {
          return color(d.group)
        })
        .call(d3.drag()
          .on('start', this.dragstarted)
          .on('drag', this.dragged)
          .on('end', this.dragended))
      this.text = svg.append('g')
        .attr('class', 'labels')
        .selectAll('text')
        .data(graphs.nodes)
        .enter().append('text')
        .attr('dy', 2)
        .attr('text-anchor', 'middle')
        .text(function (d) {
          return d.name
        })
        .attr('fill', 'white')
      this.simulation
        .nodes(graphs.nodes)
        .on('tick', this.ticked)
      this.simulation.force('link')
        .links(graphs.links)
    },
    ticked () {
      this.link
        .attr('x1', function (d) { return d.source.x })
        .attr('y1', function (d) { return d.source.y })
        .attr('x2', function (d) { return d.target.x })
        .attr('y2', function (d) { return d.target.y })
      this.node
        .attr('cx', function (d) { return d.x })
        .attr('cy', function (d) { return d.y })
      this.text
        .attr('x', function (d) { return d.x })
        .attr('y', function (d) { return d.y })
    },
    dragstarted (d) {
      if (!d3.event.active) this.simulation.alphaTarget(0.3).restart()
      d.fx = d.x
      d.fy = d.y
    },
    dragged (d) {
      d.fx = d3.event.x
      d.fy = d3.event.y
    },
    dragended (d) {
      if (!d3.event.active) this.simulation.alphaTarget(0)
      d.fx = null
      d.fy = null
    }
  },
  watch: {
    svgDialog () {
      this.opened = this.svgDialog
    }
  }
}
</script>

<style>
  .link line {
    stroke: #999;
    stroke-opacity: 0.6;
  }
  .labels text {
    pointer-events: none;
    font: 10px sans-serif;
  }
  .svgTable{
    word-break:break-all;
  }
  .svgTable>th {text-align: center;border:1px solid cyan;padding: 2px;}
  .svgTable>td {text-align: center;border:1px solid cyan;padding: 2px;}
</style>
